home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / dpmigcc5.zip / RSX / SOURCE / SYSDJ.C < prev    next >
C/C++ Source or Header  |  1994-12-12  |  15KB  |  624 lines

  1. /*****************************************************************************
  2.  * FILE: sysdj.c                                 *
  3.  *                                         *
  4.  * DESC:                                     *
  5.  *    - int 0x21, ah=0xff djgpp syscall handler                 *
  6.  *                                         *
  7.  * Copyright (C) 1993,1994                             *
  8.  *    Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld             *
  9.  *    email: rainer@mathematik.uni-bielefeld.de                 *
  10.  *                                         *
  11.  *****************************************************************************/
  12.  
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include "DPMI.H"
  16. #include "RMLIB.H"
  17. #include "PRINTF.H"
  18. #include "TIMEDOS.H"
  19. #include "STATEMX.H"
  20. #include "PROCESS.H"
  21. #include "SIGNALS.H"
  22. #include "CDOSX32.H"
  23. #include "ADOSX32.H"
  24. #include "START32.H"
  25. #include "COPY32.H"
  26. #include "RSX.H"
  27. #include "DOSERRNO.H"
  28. #include "DJIO.H"
  29.  
  30. /*
  31. **  For DJGPP programs 1.00 - 1.09 (not coff files) with big segments (4 MB)
  32. **
  33. **  move  stack,data,bss,heap
  34. **    |-CCCCC---------------------------------SSSS-DDDD-HHH-|
  35. **    0                        ^0x400000
  36. **
  37. **  to the end of text
  38. **    |-CCCCC-SSSS-DDDD-HHH-|
  39. */
  40.  
  41. void compress_memory(void)
  42. {
  43.     DWORD movedmem, newhandle, newaddress;
  44.     DWORD r_esp = ESP & ~4095L;
  45.  
  46.     /* check djgpp segment, and stack */
  47.     if (npz->data_start != 0x400000L || r_esp > npz->data_start)
  48.     return;
  49.  
  50.     movedmem = npz->membytes - r_esp;    /* memory to move */
  51.     if (r_esp - npz->stack_down < movedmem)    /* enough space? */
  52.     return;
  53.  
  54.     cpy32_32(DS, r_esp, DS, npz->stack_down, movedmem);
  55.  
  56.     if (ResizeMem(npz->stack_down + movedmem, npz->memhandle, &newhandle,
  57.           &newaddress)) {
  58.     printf("error:resize memory block\n");
  59.     return;
  60.     }
  61.     if (npz->memaddress != newaddress) {
  62.     npz->memaddress = newaddress;
  63.     SetBaseAddress(npz->code32sel, npz->memaddress);
  64.     SetBaseAddress(npz->data32sel, npz->memaddress);
  65.     SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
  66.     }
  67.     npz->p_flags |= PF_COMPRESS;
  68. }
  69.  
  70. void uncompress_memory(void)
  71. {
  72.     DWORD movedmem, newhandle, newaddress;
  73.     DWORD r_esp = ESP & ~4095L;
  74.  
  75.     /* check djgpp segment, and stack */
  76.     if (npz->data_start != 0x400000L || !(npz->p_flags & PF_COMPRESS))
  77.     return;
  78.  
  79.     if (ResizeMem(npz->membytes, npz->memhandle, &newhandle, &newaddress)) {
  80.     printf("Can't switch to parant process: ENOMEM\n");
  81.     shut_down(1);
  82.     }
  83.     if (npz->memaddress != newaddress) {
  84.     npz->memaddress = newaddress;
  85.     SetBaseAddress(npz->code32sel, npz->memaddress);
  86.     SetBaseAddress(npz->data32sel, npz->memaddress);
  87.     SetBaseAddress(npz->data32sel + sel_incr, npz->memaddress);
  88.     }
  89.     movedmem = npz->membytes - r_esp;    /* memory to move */
  90.     cpy32_32(DS, npz->stack_down, DS, r_esp, movedmem);
  91.     npz->p_flags &= ~PF_COMPRESS;
  92. }
  93.  
  94. void def_extention(char *dst, const char *ext)
  95. {
  96.     int dot, sep;
  97.  
  98.     dot = 0;
  99.     sep = 1;
  100.     while (*dst != 0)
  101.     switch (*dst++) {
  102.     case '.':
  103.         dot = 1;
  104.         sep = 0;
  105.         break;
  106.     case ':':
  107.     case '/':
  108.     case '\\':
  109.         dot = 0;
  110.         sep = 1;
  111.         break;
  112.     default:
  113.         sep = 0;
  114.         break;
  115.     }
  116.     if (!dot && !sep) {
  117.     *dst++ = '.';
  118.     strcpy(dst, ext);
  119.     }
  120. }
  121.  
  122. char *search_path(char *file, char *path)
  123. {
  124.     char *list, *end;
  125.     int i;
  126.  
  127.     strcpy(path, file);
  128.     if (rm_access(path, 4) == 0)
  129.     return path;
  130.     list = getenv("PATH");
  131.     if (list != NULL)
  132.     for (;;) {
  133.         while (*list == ' ' || *list == '\t')
  134.         ++list;
  135.         if (*list == 0)
  136.         break;
  137.         end = list;
  138.         while (*end != 0 && *end != ';')
  139.         ++end;
  140.         i = end - list;
  141.         while (i > 0 && (list[i - 1] == ' ' || list[i - 1] == '\t'))
  142.         --i;
  143.         if (i != 0) {
  144.         memcpy(path, list, i);
  145.         if (list[i - 1] != '/' && list[i - 1] != '\\' && list[i - 1] != ':')
  146.             path[i++] = '\\';
  147.         strcpy(path + i, file);
  148.         if (rm_access(path, 4) == 0)
  149.             return path;
  150.         }
  151.         if (*end == 0)
  152.         break;
  153.         list = end + 1;
  154.     }
  155.     path[0] = 0;
  156.     return (char *) 0;
  157. }
  158.  
  159. struct time32 {
  160.     DWORD secs, usecs;
  161. };
  162.  
  163. struct tz32 {
  164.     DWORD offset, dst;
  165. };
  166.  
  167. struct stat32 {
  168.     short st_dev, st_ino, st_mode, st_nlink, st_uid, st_gid, st_rdev,
  169.      st_align_for_DWORD;
  170.     long st_size, st_atime, st_mtime, st_ctime, st_blksize;
  171. };
  172.  
  173. static int set_systime(unsigned long *gmt_seconds)
  174. {
  175.     struct tm tm;
  176.     struct dos_time dt;
  177.  
  178.     gmt2tm(gmt_seconds, &tm);
  179.     dt.dtime_hour = (char) tm.tm_hour;
  180.     dt.dtime_minutes = (char) tm.tm_min;
  181.     dt.dtime_seconds = (char) tm.tm_sec;
  182.     dt.dtime_hsec = 0;
  183.     rm_settime(&dt);
  184.     return 0;
  185. }
  186.  
  187. static int make_tokens(char *argmem, char **argp)
  188. {
  189.     int i;
  190.     int args=0;
  191.  
  192.     argp[args++] = argmem;
  193.     for (i = 0; argmem[i] != '\0'; i++)
  194.     if (argmem[i] == ' ') {
  195.         argmem[i] = '\0';
  196.         if (argmem[i + 1] == ' ')
  197.         continue;
  198.         else if (argmem[i + 1] != '\0')
  199.         argp[args++] = (argmem + i + 1);
  200.     }
  201.     argp[args] = 0;
  202.  
  203.     return args;
  204. }
  205.  
  206. /*
  207. ** DJGPP 1.12 gcc compiler doesn't use this call
  208. **
  209. ** RSX starts the new process instead of loading the extender + prg
  210. */
  211. int sys_system(char *command, char **env)
  212. {
  213.     char *argmem;
  214.     char **argp;
  215.     char exe[260];
  216.     int args, r, i;
  217.  
  218.     r = strlen(command);
  219.     args = 0;
  220.     for ( i = r; i > 0 ; i--) {
  221.     if (command[i] == ' ')
  222.         args++;
  223.     }
  224.  
  225.     argmem = (char *) malloc(r+1);
  226.     argp = (char **) malloc((args+3) * sizeof(char **));
  227.     if (argmem == NULL || argp == NULL) {
  228.     if (argmem != NULL)
  229.         free(argmem);
  230.     if (argp != NULL)
  231.         free(argp);
  232.     errno = EMX_ENOMEM;
  233.     return -1;
  234.     }
  235.  
  236.     strcpy(argmem, command);
  237.  
  238.     /* make strings from command; build argv */
  239.     args = make_tokens(argmem, argp);
  240.  
  241.     /* check last argument, response file? */
  242.     if (args > 1 && argp[args - 1][0] == '@') {
  243.     int f, bytes;
  244.     char *s = &argmem[i + 2];
  245.  
  246.     args--;
  247.     f = rm_open(argp[args] + 1, RM_O_RDONLY | RM_O_DENYWR);
  248.     bytes = rm_read(f, s, 900);
  249.     s[bytes] = 0;
  250.     rm_close(f);
  251.  
  252.     argp[args++] = s;
  253.     for (i = 0; i < bytes; i++)
  254.         if (*(s + i) == 13 && *(s + i + 1) == 10) {
  255.         *(s + i) = 0;
  256.         if (i + 4 > bytes)
  257.             break;
  258.         argp[args++] = (s + i + 2);
  259.         }
  260.         else if (*(s + i) == ' ' && *(s + i + 1) > ' ') {
  261.         argp[args++] = (s + i + 2);
  262.         }
  263.     argp[args] = 0;
  264.     }
  265.  
  266.     if (rm_access(argmem, 4)) {
  267.     if (!search_path(argmem, exe)) {
  268.         errno = EMX_ENOENT;
  269.         free(argmem);
  270.         free(argp);
  271.         return -1;
  272.     } else {
  273.         argp[0] = exe;
  274.     }
  275.     }
  276.  
  277.     /* resize memory to the real used page */
  278.     compress_memory();
  279.  
  280.     r = exec32(P_WAIT, argp[0], args, argp, org_envc, org_env);
  281.  
  282.     /* if error, try a real-mode prg */
  283.     if (r == EMX_ENOEXEC)
  284.     r = realmode_prg(argp[0], &(argp[0]), org_env);
  285.  
  286.     uncompress_memory();
  287.  
  288.     free(argmem);
  289.     free(argp);
  290.  
  291.     return r;
  292. }
  293.  
  294. /*
  295. ** DJGPP 1.11 exec/spawn
  296. ** uses TRANSLATION services by DPMI to simulate 0x21 ah=9x4b
  297. **
  298. ** RSX starts the new process instead of loading the extender + prg
  299. */
  300. int simulate_go32_exec(void)
  301. {
  302.     TRANSLATION tr;
  303.     DWORD offset;
  304.     WORD *pblock;
  305.     char **env;
  306.     char *name;
  307.     int z, args;
  308.     char *cmd;
  309.     static char cline[128];
  310.  
  311.     cpy32_16(ES, EDI, & tr, sizeof(tr));
  312.  
  313.     /* get pointer to program name */
  314.     tr.edx += (DWORD) tr.ds << 4;
  315.     offset = tr.edx - ((DWORD)ds16real << 4);
  316.     name = (char *)(UINT)offset;
  317.  
  318.     /* get pointer to exec block */
  319.     tr.ebx += (DWORD) tr.es << 4;
  320.     offset = tr.ebx - ((DWORD)ds16real << 4);
  321.     pblock = (WORD *)(UINT)offset;
  322.  
  323.     /* get args */
  324.     offset = ((DWORD) pblock[2] << 4) + (DWORD) pblock[1];
  325.     offset -= (DWORD) ds16real << 4;
  326.     cmd = (char *) ((UINT) offset + 1);
  327.  
  328.     /* build comand line */
  329.     strcpy(cline, name);
  330.     z = strlen(cline);
  331.     for ( ; z < sizeof(cline) ; z++) {
  332.     cline[z] = *cmd;
  333.     if (cline[z] == 13)
  334.         break;
  335.     cmd++;
  336.     }
  337.     cline[z] = '\0';
  338.  
  339.     /* environment */
  340.     if (pblock[0]) {
  341.     offset = (DWORD) pblock[0] << 4;
  342.     offset -= ((DWORD)ds16real << 4);
  343.     env = (char **)(UINT)offset;
  344.     }
  345.     else
  346.     env = org_env;
  347.  
  348.     /*** just like go32 **************
  349.     npz->regs.eax = 0x300;
  350.     if (execute_dpmi_function())
  351.     r = -1;
  352.     else
  353.     r = (int) tr.eax & 0xFF;
  354.     *********************************/
  355.  
  356.     if (strstr(cline, "!proxy")) {
  357.     /* go32 !proxy argc seg off seg off info */
  358.     char *param[12];    /* if more in future */
  359.     WORD *newargs;
  360.  
  361.     make_tokens(cline, param);
  362.     args = hexstr2int(param[2]);
  363.  
  364.     offset = (DWORD) (UINT) hexstr2int(param[3]) << 4;
  365.     offset -= ((DWORD)ds16real << 4);
  366.     newargs = (WORD *) ((UINT) offset + (UINT) hexstr2int(param[4]));
  367.  
  368.     strcpy(iobuf, (char *) ((UINT)newargs[0] + (UINT)offset));
  369.     for ( z = 1; z < args; z++) {
  370.         strcat(iobuf, " ");
  371.         strcat(iobuf, (char *)((UINT)newargs[z] + (UINT)offset));
  372.     }
  373.     cmd = iobuf;
  374.     } else
  375.     cmd = cline;
  376.  
  377.     /* but it's better to handle it self */
  378.     return sys_system(cmd, NULL);
  379. }
  380.  
  381. static long my_daylight;
  382. static long my_timezone;
  383.  
  384. int i_21_ff(void)
  385. {
  386.     DWORD p1 = EBX, p2 = ECX;
  387.     int r, i, handle;
  388.  
  389.     switch (AX & 0xff) {    /* al=? */
  390.     case 1:
  391.     handle = get_empty_proc_filp();
  392.     if (handle < 0) {
  393.         EAX = EMX_EBADF;
  394.         return CARRY_ON;
  395.     }
  396.     strcpy32_16(DS, p1, iobuf);    /* p1 -> iobuf */
  397.     r = dj_creat(iobuf);
  398.     if (r >= 0) {
  399.         npz->filp[handle]->f_mode = FMODE_READ | FMODE_WRITE;
  400.         npz->filp[handle]->f_doshandle = r;
  401.         npz->filp[handle]->f_op = & msdos_fop;
  402.         r = handle;
  403.     }
  404.     break;
  405.  
  406.     case 2:
  407.     handle = get_empty_proc_filp();
  408.     if (handle < 0) {
  409.         EAX = EMX_EBADF;
  410.         return CARRY_ON;
  411.     }
  412.     strcpy32_16(DS, p1, iobuf);    /* p1 -> iobuf */
  413.     i = (int) (UINT) p2;
  414.     r = dj_open(iobuf, i);
  415.     if (r >= 0) {
  416.         npz->filp[handle]->f_mode = FMODE_READ | FMODE_WRITE;
  417.         npz->filp[handle]->f_doshandle = r;
  418.         npz->filp[handle]->f_op = & msdos_fop;
  419.         r = handle;
  420.     }
  421.     break;
  422.  
  423.     case 3:            /* fstat */
  424.     {
  425.         struct stat32 statbuf32;
  426.         struct stat statbuf;
  427.  
  428.         handle = get_dos_handle((WORD) p1);
  429.         if (handle < 0) {
  430.         EAX = EMX_EBADF;
  431.         return CARRY_ON;
  432.         } else
  433.         p1 = handle;
  434.  
  435.         r = sys_fstat(handle, &statbuf);
  436.         if (r == -1) {
  437.         errno = doserror_to_errno(_doserrno);
  438.         break;
  439.         }
  440.         statbuf32.st_dev = (short) statbuf.st_dev;
  441.         statbuf32.st_ino = (short) statbuf.st_ino;
  442.         statbuf32.st_mode = (short) statbuf.st_mode;
  443.         statbuf32.st_nlink = (short) statbuf.st_nlink;
  444.         statbuf32.st_uid = 42;
  445.         statbuf32.st_gid = 42;
  446.         statbuf32.st_rdev = (short) statbuf.st_rdev;
  447.         statbuf32.st_size = statbuf.st_size;
  448.         statbuf32.st_atime = statbuf.st_atime;
  449.         statbuf32.st_mtime = statbuf.st_mtime;
  450.         statbuf32.st_ctime = statbuf.st_ctime;
  451.         statbuf32.st_blksize = 4096;
  452.         /* stat -> p2 */
  453.         cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
  454.     }
  455.     break;
  456.  
  457.     case 4:            /* get time & day */
  458.     {
  459.         struct time32 time32;
  460.         struct tz32 tz32;
  461.         struct dos_date dd;
  462.         struct dos_time dt;
  463.  
  464.         if (p2) {
  465.         tz32.offset = my_timezone;
  466.         tz32.dst = my_daylight;
  467.         cpy16_32(DS, p2, &tz32, (DWORD) sizeof(tz32));
  468.         }
  469.         if (p1) {
  470.         unsigned long gmt;
  471.         rm_getdate(&dd);
  472.         rm_gettime(&dt);
  473.         gmt = dos2gmt(&dd, &dt);
  474.         time32.secs = gmt;
  475.         time32.usecs = (DWORD) dt.dtime_hsec * 10;
  476.         cpy16_32(DS, p1, &time32, (DWORD) sizeof(time32));
  477.         }
  478.         r = 0;
  479.     }
  480.     break;
  481.  
  482.     case 5:            /* set time & day */
  483.     {
  484.         struct time32 time32;
  485.         struct tz32 tz32;
  486.  
  487.         if (p2) {
  488.         cpy32_16(DS, p2, &tz32, (DWORD) sizeof(tz32));
  489.         my_timezone = tz32.offset;
  490.         my_daylight = (WORD) tz32.dst;
  491.         }
  492.         if (p1) {
  493.         cpy32_16(DS, p1, &time32, (DWORD) sizeof(time32));
  494.         set_systime((unsigned long *) &(time32.secs));
  495.         }
  496.         r = 0;
  497.     }
  498.     break;
  499.  
  500.     case 6:            /* stat */
  501.     {
  502.         struct stat32 statbuf32;
  503.         struct stat statbuf;
  504.         char fname[160];
  505.  
  506.         memset(&statbuf, 0, sizeof(statbuf));
  507.         strcpy32_16(DS, p1, fname);
  508.  
  509.         r = sys_stat(fname, &statbuf);
  510.         if (r == -1) {
  511.         errno = doserror_to_errno(_doserrno);
  512.         break;
  513.         }
  514.         statbuf32.st_dev = (short) statbuf.st_dev;
  515.         statbuf32.st_ino = (short) statbuf.st_ino;
  516.         statbuf32.st_mode = (short) statbuf.st_mode;
  517.         statbuf32.st_nlink = (short) statbuf.st_nlink;
  518.         statbuf32.st_uid = 42;
  519.         statbuf32.st_gid = 42;
  520.         statbuf32.st_rdev = (short) statbuf.st_rdev;
  521.         statbuf32.st_size = statbuf.st_size;
  522.         statbuf32.st_atime = statbuf.st_atime;
  523.         statbuf32.st_mtime = statbuf.st_mtime;
  524.         statbuf32.st_ctime = statbuf.st_ctime;
  525.         statbuf32.st_blksize = 512;
  526.         /* stat -> p2 */
  527.         cpy16_32(DS, p2, &statbuf32, (DWORD) sizeof(statbuf32));
  528.     }
  529.     break;
  530.  
  531.     case 7:
  532.     strcpy32_16(DS, p1, iobuf);
  533.     r = sys_system(iobuf, NULL);
  534.     if (r) {
  535.         errno = r;
  536.         r = -1;
  537.     }
  538.     break;
  539.  
  540.     case 8:
  541.     handle = get_dos_handle((WORD) p1);
  542.     if (handle < 0) {
  543.         EAX = EMX_EBADF;
  544.         return CARRY_ON;
  545.     } else
  546.         p1 = (long) handle;
  547.  
  548.     i = rm_ioctl_getattr(handle);
  549.     if (p2 & 0x8000)    /* O_BINARY */
  550.         i |= 0x20;
  551.     else
  552.         i &= ~0x20;
  553.     rm_ioctl_setattr(handle, i);
  554.     r = dj_setmode((int) p1, (int) p2);
  555.     break;
  556.  
  557.     case 9:
  558.     strcpy32_16(DS, p1, iobuf);    /* p1 -> iobuf */
  559.     r = dj_chmod(iobuf, (int) p2);
  560.     break;
  561.  
  562.     case 10:    /* DOS 0x4B */
  563.     r = simulate_go32_exec();
  564.     break;
  565.  
  566.     default:
  567.     r = -1;
  568.     errno = EMX_EIO;
  569.     break;
  570.     }                /* switch */
  571.  
  572.     if (r == -1) {
  573.     EAX = errno;
  574.     return CARRY_ON;
  575.     } else {
  576.     EAX = (long) r;
  577.     return CARRY_OFF;
  578.     }
  579. }
  580.  
  581. /* go32 debug functions */
  582. #define EXTERNAL_DEBUGGER_EXECUTE    0
  583. #define EXTERNAL_DEBUGGER_GETINFOPTR    1
  584.  
  585. typedef struct {
  586.   WORD version;     /* set to version number of interface */
  587.   WORD a_tss_ofs;    /* pointer to TSS for debugged program */
  588.   WORD a_tss_seg;
  589.   WORD filename_ofs;    /* points to name of file being debugged */
  590.   WORD filename_seg;
  591.   WORD filename_len;
  592.   WORD areas_ofs;    /* from paging.c */
  593.   WORD areas_seg;
  594.   DWORD app_base;    /* linear base address of application */
  595.   DWORD dr[8];        /* debug registers, set when a_tss runs */
  596.   DWORD ansi_mode;    /* if set, OK to emit ansi control codes */
  597. } ExternalDebuggerInfo;
  598.  
  599. int i_21_fe(void)
  600. {
  601.     puts("external debugger not supported");
  602.     do_exit4c(0);
  603.     return 0;
  604.  
  605.     /*
  606.     ext_debug_info.version = EXTERNAL_DEBUGGER_VERSION;
  607.  
  608.     ext_debug_info.a_tss_ofs = FP_OFF(&a_tss);
  609.     ext_debug_info.a_tss_seg = ourDSsel;
  610.  
  611.     ext_debug_info.filename_ofs = FP_OFF(running_fname);
  612.     ext_debug_info.filename_seg = ourDSsel;
  613.     ext_debug_info.filename_len = strlen(running_fname);
  614.  
  615.     ext_debug_info.areas_ofs = FP_OFF(&areas);
  616.     ext_debug_info.areas_seg = ourDSsel;
  617.  
  618.     ext_debug_info.app_base = ARENA;
  619.     ext_debug_info.ansi_mode = use_ansi;
  620.  
  621.     memset(ext_debug_info.dr, 32, 0);
  622.     */
  623. }
  624.